import base64, hashlib, socket, threading
import time
from datetime import datetime

# sshSocket输出进程 输出ssh通道中的内容 输出到客户端
from ..tools.socketGetHeader import get_headers
from ..tools.socketSendMsg import send_msg
from ..tools.truncateUtf8Chars import truncate_utf8_chars


class sshPrintThread(threading.Thread):  # 继承父类threading.Thread
    def __init__(self, sshChannel, outport, trandom):
        threading.Thread.__init__(self)
        self.sshChannel = sshChannel
        self.outport = outport
        self.trandom = trandom

    def run(self):  # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        socket.setdefaulttimeout(36000)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建 socket 对象
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('127.0.0.1', self.outport))  # 绑定端口
        s.listen(5)  # 等待客户端连接
        handler_accept(s, self.sshChannel, self.trandom)

def handler_msg(connect, sshChannel, trandom):
    # print("derBUG 发送消息进程 : ")
    with connect as connect_ptr:
        while True:
            out = sshChannel.recv(65535)
            if len(out) == 0:
                print("发送结果为空!")
                break
            send_msg(connect_ptr, bytes(out.decode(encoding='UTF-8',errors='ignore'), encoding="utf-8"))

            # 记录命令和结果到日志文件
            sshIP = sshChannel.get_name()
            # ISOTIMEFORMAT = '%Y年%m月%d日 %H点%M分%S秒'
            with open('log/' + sshIP + '/' + sshIP + '-' + datetime.now().strftime('%Y年%m月%d日').__str__() + '-' + trandom.__str__() + '.txt',mode='a+',encoding='utf-8') as note:
                # 应该判断值的内容是什么按键 不等于退格键 不等于其他键
                # 输入命令过程中按了长度超过1的键，就会使日志中的命令换行
                if len(out.decode(encoding='UTF-8',errors='ignore')) > 1:

                    # note.write("\n" + "JainaCmdResultTime:" + time.time().__str__() + " JainaCmdResult:" + out.decode(encoding='UTF-8',errors='ignore').replace("\n","") + " JainaCmdResultEnd")

                    # 设置退格键不换行 如果按键不等于退格键
                    if out.__str__() != "b\'\\x08\\x1b[K\'":
                        # print(out.__str__())
                        if out.__str__() == "b\'\\r\\n\'":
                            note.write(out.decode())
                        else:
                            note.write(
                            "\n" + "JainaCmdResultTime:" + time.time().__str__() + " JainaCmdResult:" + out.decode(encoding='UTF-8',errors='ignore').replace("\n","") + " JainaCmdResultEnd")
                        # if out.__str__() == ""
                    # 设置退格键在日志中删除记录（例如：lsbls命令，点击退格键再输入k，日志中仍会存在应该删除的s）
                    else:
                        #删除最后一个字符
                        # 所以日志中会出现这种情况JainaCmdTime:1670334398.1555126 JainaCmd:c
                        # JainaCmdTime:1670334398.335767 Jain
                        # TODO　2022年12月6日 现在应该改成删除最后一行　或者　把退格符号还给日志文件
                        # truncate_utf8_chars('log/' + sshIP + '/' + sshIP + '-' + datetime.now().strftime('%Y年%m月%d日').__str__() + '-' + trandom.__str__() + '.txt', 1)
                        # now
                        note.write(out.decode())
                else:
                    # 记录输入的单个长度为1的按键到日志(将l /n s /n b /n l /n k /n 变成lsblk)
                    # TODO 输入命令时，键盘左右移动问题
                    if out.__str__() == "b\'\\x08\'":
                        note.write(
                            "\n" + "JainaCmdResultTime:" + time.time().__str__() + " JainaCmdResult:" + "[D" + " JainaCmdResultEnd")
                    else:
                        note.write("\n" + "JainaCmdTime:" + time.time().__str__() + " JainaCmd:")
                        note.write(out.decode().replace("\n",""))
                    # 可以输出控制字符串
                    print(out.__str__())
        # 终端debug 会导致tree结果解码异常
            # print("发送的结果 : " + out.decode(encoding='UTF-8',errors='ignore') + "结束")
            # print(out.__str__())
# global sshChannel
def handler_accept(sock, sshChannel, trandom):
    while True:
        conn, addr = sock.accept()
        data = conn.recv(8096)
        headers = get_headers(data)

        # 对请求头中的sec-websocket-key进行加密
        response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
                       "Upgrade:websocket\r\n" \
                       "Connection: Upgrade\r\n" \
                       "Sec-WebSocket-Accept: %s\r\n" \
                       "WebSocket-Location: ws://%s\r\n\r\n"         # 加盐操作,此处是H5规范定义好的
        magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
        if headers.get('Sec-WebSocket-Key'):
            value = headers['Sec-WebSocket-Key'] + magic_string
        # 对数据进行加解密
        ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
        response_str = response_tpl % (ac.decode('utf-8'), headers.get("Host"))
        # 相应握手包数据
        conn.sendall(bytes(response_str, encoding="utf-8"))
        handler_msg(conn, sshChannel, trandom)
